package com.example.dezhou_puke.service;

import com.example.dezhou_puke.entity.ComparePuke;
import com.example.dezhou_puke.entity.Puke;
import com.example.dezhou_puke.enums.Level;
import com.example.dezhou_puke.utils.DeZhouPuKeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: DeZhouPuKeService
 * @Description: 德州扑克  10  种牌型比较大小（因之前不了解德州扑克，如有不对敬请谅解！）
 *        备注：   J:11 , Q:12,   K:13,   A:14    非同花大顺时 A :1
 * @Author: YangGuisen
 * @Date: 2018/6/5 19:03
 * @Version: 1.0
 */
@Service
public class DeZhouPuKeServiceImpl implements DeZhouPuKeService {

    static Logger logger = LoggerFactory.getLogger(DeZhouPuKeServiceImpl.class);


    @Override
    public void excuter(List<Puke> fivePukes, List<Puke> fivePukes2) {

        logger.info("原生的牌为1： " + fivePukes);
        logger.info("原生的牌为2： " + fivePukes2);

        //简单验证两手牌
        if(fivePukes.size()==5 && fivePukes2.size()==5){
            List<Puke> allFivePukes = new ArrayList<>();
            allFivePukes.addAll(fivePukes);
            allFivePukes.addAll(fivePukes2);
            if (!DeZhouPuKeUtils.judgePuKesListIsAuthorized(fivePukes)
                    || !DeZhouPuKeUtils.judgePuKesListIsAuthorized(fivePukes2)
                    || !DeZhouPuKeUtils.judgePuKesListIsAuthorized(allFivePukes)) {
                logger.info("输入的牌有误请重新输入！： ");
                return;
            }
        }else{
            logger.info("输入的牌有误请重新输入！： ");
            return;
        }


        //开始比较
        ComparePuke comparePukeA = decideCardTypeAboutColorAndShunZi(fivePukes);
        ComparePuke comparePukeB = decideCardTypeAboutColorAndShunZi(fivePukes2);
        decideCardTypeAboutTher(comparePukeA);
        decideCardTypeAboutTher(comparePukeB);
        comparePuKes(comparePukeA, comparePukeB);
    }


    /**
     * 判断牌型 1同花大顺 2，同花顺 3，同花 4，顺子
     *
     * @param fivePukes
     * @return
     */
    private ComparePuke decideCardTypeAboutColorAndShunZi(List<Puke> fivePukes) {
        Integer lastIndex = fivePukes.size() - 1;
        ComparePuke comparePuke = new ComparePuke();

        boolean sameColor = DeZhouPuKeUtils.isSameColor(fivePukes);
        boolean shunZi = DeZhouPuKeUtils.isShunZi(fivePukes);

        if (sameColor && shunZi) { //是同花又是顺子 9   10
            if (fivePukes.get(lastIndex).getNum() == 14) { //是否是同花大顺 14是A
                comparePuke.setLevel(Level.ROYAL_FLUSH.getLevel());
            } else {
                comparePuke.setLevel(Level.STRAIGHT_FLUSH.getLevel());
            }
        } else if (sameColor && !shunZi) { //是同花不是顺子
            comparePuke.setLevel(Level.FLUSH.getLevel());
        } else if (!sameColor && shunZi) {
            comparePuke.setLevel(Level.STRAIGHT.getLevel()); //顺子
        }
        comparePuke.setPukes(fivePukes);
        return comparePuke;
    }


    /**
     * 判断  除 1同花大顺 2，同花顺 3，同花 4，顺子 以外的牌型
     *
     * @param comparePuke
     * @return
     */
    private ComparePuke decideCardTypeAboutTher(ComparePuke comparePuke) {
        List<Puke> fivePukes = comparePuke.getPukes();
        Map<Integer, Integer> map = new HashMap<>();
        fivePukes.forEach(k -> {
            if (!map.containsKey(k.getNum())) {
                map.put(k.getNum(), 1);
            } else {
                map.put(k.getNum(), map.get(k.getNum()) + 1);
            }
        });

        List<Integer> resultList = new ArrayList<>();
        map.entrySet().stream().sorted(Map.Entry.<Integer, Integer>comparingByValue().reversed()).forEach(k -> resultList.add(k.getValue()));


        Integer result = resultList.size() * 10 + resultList.get(0);
        /**
         * 牌型为：4条时   resultList的size是2    同一张牌最大出现的次数 4
         * 牌型为：3+1对时   resultList的size是2    同一张牌最大出现的次数 3
         * 牌型为：3张同点时   resultList的size是3   同一张牌最大出现的次数 3
         * 牌型为：2对时   resultList的size是3   同一张牌最大出现的次数 2
         * 牌型为：1对时   resultList的size是4   同一张牌最大出现的次数 2
         */
        switch (result) {
            case 24:
                comparePuke.setLevel(Level.FOUR_OF_A_KIND.getLevel());
                break;
            case 23:
                comparePuke.setLevel(Level.FULLHOUSE.getLevel());
                break;
            case 33:
                comparePuke.setLevel(Level.THREE_OF_A_KIND.getLevel());
                break;
            case 32:
                comparePuke.setLevel(Level.TWO_PAIRS.getLevel());
                break;
            case 42:
                comparePuke.setLevel(Level.ONE_PAIR.getLevel());
                break;
        }
        if (null == comparePuke.getLevel()) { //仍然为空是则是高牌
            comparePuke.setLevel(Level.HIGH_CARD.getLevel());
        }
        comparePuke.setPukes(fivePukes);
        return comparePuke;
    }

    /**
     * 比较大小
     *
     * @param comparePukeA
     * @param comparePukB
     */
    private void comparePuKes(ComparePuke comparePukeA, ComparePuke comparePukB) {

        Integer a;
        Integer b;
        if (comparePukeA.getLevel() != comparePukB.getLevel()) {
            a = comparePukeA.getLevel();
            b = comparePukB.getLevel();
        } else {
            a = convertToNumber(comparePukeA.getLevel(), comparePukeA.getPukes());
            b = convertToNumber(comparePukB.getLevel(), comparePukB.getPukes());
        }

        logger.info("------------------------------比较结果为： --------------------");
        logger.info(" 手牌A： " + comparePukeA.getPukes() + " 牌型为： " + Level.getLevelDesc(comparePukeA.getLevel()));
        logger.info(" 手牌B： " + comparePukB.getPukes() + " 牌型为： " + Level.getLevelDesc(comparePukB.getLevel()));
        if (a < b) {
            logger.info("手牌A  [ 小于 ] 手牌B");
        } else if (a > b) {
            logger.info("手牌A  [ 大于 ]  手牌B");
        } else {
            logger.info("手牌A  [ 平手 ]  手牌B");
        }
    }

    /**
     * 同牌型转换为数字比较大小
     *
     * @param level
     * @param fivePukes
     * @return
     */
    private Integer convertToNumber(Integer level, List<Puke> fivePukes) {
        StringBuffer stringBuffer = new StringBuffer(level);
        fivePukes.forEach(k -> {
            if (level != 10 && k.getNum() == 14) {
                stringBuffer.append("01");
            } else {
                stringBuffer.append(k.getNum() < 10 ? "0" + k.getNum() : k.getNum());
            }
        });
        return Integer.parseInt(stringBuffer.toString());
    }

}
